%   Initialization
clear; close all; clc;

%   ========    Part1: Ploting Data Sets    ========
%   Load the data
data = load('data2.txt');
%   Initialize the variables of the data
X = data(:, 1:2);
y = data(:, 3);
fprintf('Plotting the data with + indicating (y = 1) examples and o indicating (y = 0) examples.\n');
%   Plot the data
plotData(X, y);
%   Set the x−axis label
xlabel('Microchip Test 1');
%   Set the y−axis label
ylabel('Microchip Test 2');
%   Add the legend to the plot
legend('y = 1', 'y = 0');
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part2: Regularized Logistic Regression    ========
%   Map the data to the polynomial features
X = mapFeature(X(:, 1), X(:, 2));
%   Initialize the fitting parameters
initial_theta = zeros(size(X, 2), 1);
%   Set the regularization parameter lambda
lambda = 1;
%   Compute the initial cost and gradient
[cost, grad] = costFunctionReg(initial_theta, X, y, lambda);
fprintf('Cost at initial theta (zeros): %f\n', cost);
fprintf('Gradient at initial theta (zeros): \n');
fprintf(' %f \n', grad);
%   Pause the program
fprintf('Program paused. Press any key to continue.\n'); pause;

%   ========    Part3: Regularization And Accuracy    ========
%   Initialize the fitting parameters
initial_theta = zeros(size(X, 2), 1);
%   Set the regularization parameter lambda
lambda = 0.5;
%   Set the options for fminunc
options = optimset('GradObj', 'on', 'MaxIter', 400);
%   Run the fminunc function to train the theta
[theta, J, exit_flag] = fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options);
%   Plot the decision boundary
plotDecisionBoundary(theta, X, y);
%   Set the title of the plot
title(sprintf('lambda = %g', lambda));
%   Set the x−axis label
xlabel('Microchip Test 1');
%   Set the y−axis label
ylabel('Microchip Test 2');
%   Add the legend to the plot
legend('y = 1', 'y = 0', 'Decision boundary');
%   Compute the accuracy on our training set
p = predict(theta, X);
fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);
